using System;
using System.Collections.Generic;
using System.Linq;

namespace SilverAmp.Common.DecoupledEvents
{
    /// <summary>
    /// Base class for Decoupled events
    /// </summary>
    public class DecoupledEventBase
    {
        private List<IDecoupledEventSubscription> _subscriptions;

        protected DecoupledEventBase()
        {
            _subscriptions=new List<IDecoupledEventSubscription>();
        }
        protected virtual SubscriptionToken InternalSubscribe(IDecoupledEventSubscription eventSubscription)
        {
            eventSubscription.SubscriptionToken = new SubscriptionToken();
            lock (_subscriptions)
            {
                _subscriptions.Add(eventSubscription);
            }
            return eventSubscription.SubscriptionToken;
        }

        protected virtual void InternalPublish(params object[] arguments)
        {
            IEnumerable<Action<object[]>> actions = Prune();
            foreach (var action in actions)
            {
                action(arguments);
            }
        }
        private IEnumerable<Action<object[]>> Prune()
        {
            var returnList = new List<Action<object[]>>();
            lock (_subscriptions)
            {
                for (var i = _subscriptions.Count - 1; i >= 0; i--)
                {
                    Action<object[]> listItem =
                        _subscriptions[i].GetExecutionStrategy();

                    if (listItem == null)
                    {                        
                        _subscriptions.RemoveAt(i);
                    }
                    else
                    {
                        returnList.Add(listItem);
                    }
                }
            }

            return returnList;
        }

        public virtual void Unsubscribe(SubscriptionToken token)
        {
            lock (_subscriptions)
            {
                IDecoupledEventSubscription subscription = _subscriptions.FirstOrDefault(evt => evt.SubscriptionToken == token);
                if (subscription != null)
                {
                    _subscriptions.Remove(subscription);
                }
            }
        }

    }
}